package com.lvyq.myplayer.widget

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
 import com.lvyq.myplayer.R
import com.lvyq.myplayer.model.lrc.LrcBean
import org.jetbrains.anko.doAsync

/**
 * 文件描述：LrcView
 * 作者：lvyq
 * 创建时间：2025-03-12
 * 修改时间：2025-03-12
 */
class LrcView: View {
    //初始化画笔
    val paint by lazy {
        //ANTI_ALIAS_FLAG 抗锯齿
        Paint(Paint.ANTI_ALIAS_FLAG)
    }

    var viewW:Int = 0
    var viewH:Int = 0

    //播放中字体大小
    var lrcBigSize=0f
    //非播放中字体大小
    var lrcSmallSize=0f
    //播放中颜色
    var lrcShowingColor=0
    //非播放中颜色
    var lrcPendingColor=0
    //自定义行高
    var lineHeight=0

    var lrcLst =ArrayList<LrcBean>()
    var centerLine = 0


    //总时长
    var durationTime = 0
    //偏移时间
    var processTime =0

    var updateByPro=true

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    init {
        //初始化
        lrcBigSize=resources.getDimension(R.dimen.lrcBigSize)
        lrcSmallSize=resources.getDimension(R.dimen.lrcSmallSize)
        lrcShowingColor=resources.getColor(R.color.colorPrimary)
        lrcPendingColor=resources.getColor(R.color.white)

        lineHeight=resources.getDimensionPixelOffset(R.dimen.lineHeight)
        //设置画笔绘制位置  x方向居中
        paint.textAlign=Paint.Align.CENTER

        //模拟歌词
//        for (i in 0..30){
//            lrcLst.add(LrcBean(2000*i,"正在播放第 $i 行歌词"))
//        }
    }


    /**
     * 重写绘制文本
     */
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)


        //绘制内容 -居中显示
        //x = viewW/2-textW/2
        //y = viewH/2 +textH/2
        if (lrcLst.size==0){
            drawSingleLrc(canvas)
        }else{
            drawMultipleLrc(canvas)
        }

        //绘制多行



    }

    /**
     * 绘制多行歌词
     */

    //偏移Y值
    var offset_Y = 0f
    private fun drawMultipleLrc(canvas: Canvas?) {
        /**
         *  歌词滚动
         *  求居中行偏移量y
         *  偏移y=偏移百分比*行高
         *  偏移百分比=偏移时间/行可用时间
         *  偏移时间=process-居中行开始时间
         *  行可用时间:
         *  最后一行>
         *  行可用时间=duration -最后一行开始时间
         *  其它行>
         *  行可用时间=下一行开始时间-居中行开始时间
         */

        if (updateByPro){
            //行可用时间
            var lineTime=0
            //居中行开始时间
            var centerS  = lrcLst.get(centerLine).startTime
            if (centerLine==lrcLst.size-1){
                //最后一行
                lineTime = durationTime - lrcLst.get(lrcLst.size-1).startTime
            }else{
                //其它行
                var nextS = lrcLst.get(centerLine+1).startTime

                lineTime=nextS-centerS
            }
            //偏移时间 process-居中行开始时间
            var  offsetTime = processTime-centerS
            //偏移百分比=偏移时间/行可用时间
            var offSetPer =  offsetTime/(lineTime.toFloat())
            // 偏移y=偏移百分比*行高
            offset_Y = offSetPer*lineHeight



        }
        val centerText = lrcLst.get(centerLine).content
        //居中行Y值
        val bounds = Rect()
        paint.getTextBounds(centerText,0,centerText.length,bounds)
        val textH = bounds.height()
        //居中行Y
        val centerY = viewH/2+textH/2-offset_Y
        //其它行的Y坐标 centerY+（行号-据中行行号）* 行高   从上到下从0递增
        for ((index,value ) in lrcLst.withIndex()){
            val curX  = viewW/2
            val curY = centerY+(index-centerLine)*lineHeight
            val curText = lrcLst.get(index).content
            //绘制
            if (index==centerLine){
                //初始化画笔颜色和大小
                paint.color=lrcShowingColor
                paint.textSize=lrcBigSize
            }else{
                //初始化画笔颜色和大小
                paint.color=lrcPendingColor
                paint.textSize=lrcSmallSize
            }
            //超出边界处理
            //处理上边界
            if(curY<0) continue
            //下边界
            if (curY>viewH+lineHeight) break //结束绘制
            canvas?.drawText(curText,curX.toFloat(),curY.toFloat(),paint)
        }
    }

    //绘制单行
    private fun drawSingleLrc(canvas: Canvas?) {
        //通过画笔获取文本的宽度和高度
        var text ="正在加载歌词..."
        val bounds = Rect()
        paint.getTextBounds(text,0,text.length,bounds)
        val textW =bounds.width()
        val textH =bounds.height()
        val x = viewW/2-textW/2
        val y = viewH/2+textH/2
        canvas?.drawText(text,viewW/2.toFloat(),y.toFloat(),paint)

    }

    /**
     * 布局后执行，重写，获取view宽高
     */
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        viewH=h
        viewW=w
    }

    /**
     * 根据时间更新进度
     */
    fun updateProcess(process: Int){
        if (!updateByPro) return
        //获取居中行
        //判断居中行是否是最后一行
        if (process>=lrcLst.get(lrcLst.size-1).startTime){
            centerLine=lrcLst.size-1
        }else if (process<=lrcLst.get(0).startTime){
            centerLine=0
        }
        else{
            //其它居中行，便利
            for (index in 0..lrcLst.size-2){
                //process大于等于当前行播放时间 且小于下一行开始时间
                val curStartTime  =lrcLst.get(index).startTime
                val nextStartTime = lrcLst.get(index+1).startTime
                if (process>=curStartTime && process<nextStartTime){
                    centerLine=index
                    break
                }
            }
        }

        //重新绘制
        invalidate() //调用重写的onDraw 方法
        //postInvalidate() // onDraw ,子线程刷新绘制
        //requestLayout()//  view布局参数改变时刷新
        processTime=process
    }

    /**
     * 歌曲总时长
     */
    fun setSongDuration(duration:Int){
        durationTime = duration
    }

    /**
     * 设置歌词
     */
    fun setLrcContent(lrcList:ArrayList<LrcBean>){
          lrcLst=lrcList
    }

    /**
     * 手势控制歌曲进度
     */
    var downY = 0f
    //记录自动歌词滚动时产生偏移量，并参与拖动计算，避免歌词抖动，尤其是开始播放时，拖动时，第一行会跳动到中间为止
    var markY = 0f
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when(event?.action){
            MotionEvent.ACTION_DOWN->{
                //停止通过进度更新歌词
                updateByPro=false
                //记录手指按下时Y值
                downY=event.y
                //记录自动播放时的偏移量
                markY=offset_Y
            }

            MotionEvent.ACTION_UP->{
                //通过进度更新
                updateByPro=true
            }

            //歌词滑动
            MotionEvent.ACTION_MOVE->{
                //记录当前移动Y值
                val endY = event.y
                //手指移动y值
                val offY = downY-endY
                //重新设置居中行偏移
                offset_Y=offY+markY

                //如果最终Y的偏移量大于等于行高，重新定义居中行
                //Math.abs 获取绝对值，因为往上+ 往下-
                if (Math.abs(offset_Y) >= lineHeight){
                    //求居中行行号偏移
                    val  offsetLine = (this.offset_Y/lineHeight).toInt()
                    centerLine+=offsetLine

                    //centerLine 边界处理
                    if (centerLine<0){
                        centerLine=0
                    }else if (centerLine>lrcLst.size-1){
                        centerLine=lrcLst.size-1
                    }
                    //downY重新设置
                    downY=endY
                    //重新确定偏移Y值
                    offset_Y=offset_Y%lineHeight
                    //重新记录Y的偏移量
                    markY=offset_Y

                    //更新播放进度
                    listener?.invoke(lrcLst.get(centerLine).startTime)
                }

                //重新绘制
                invalidate()
            }

        }

        return true
    }

    //定义进度回调函数
   var listener:((progress:Int)->Unit)? = null
    //设置进度回调函数
    fun setProgressListener( listener:((progress:Int)->Unit)){
        this.listener=listener
    }
}